/*
 * Copyright (C) 2013 Daniel Treffenstädt <daniel@treffenstaedt.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "StyleParser.h"

#include "../Core/Log.h"

#include "../Painter/Font.h"

O_START_NAMESPACE

StyleParser::StyleParser(String text)
{
	m_state			= State::Root;
	m_lastState		= State::Root;
	m_lastString	= "";
	m_option		= "";
	m_optionValue	= "";
	m_wName			= "";
	m_wClass		= "";
	m_wId			= "";
	m_lastChar		= ' ';

	int line		= 1;
	int col			= 1;

	for (int i = 0; i < text.length(); i++)
	{
		Char c	= text.charAt(i);
		if (c != '\t')
		{
			if (!parseChar(c))
			{
				Log::message("Stylesheet: line " + String::number(line) + ", column " + String::number(col) + " unexpected character: '" + c + "'.");
				break;
			}
			col++;
			if (c == '\n')
			{
				line++;
				col	= 1;
			}
		}
		m_lastChar	= c;
	}
}

bool StyleParser::parseChar(Char c)
{
	if (c == ' ')
	{
		if (m_state == State::OptionValue && m_option == "font-family" && m_lastChar != ':' && m_lastChar != ' ')
		{
			m_optionValue	+= c;
		}
	}
	else if (m_state == State::Comment)
	{
		if (c == '\n')
		{
			setState(m_lastState);
		}
	}
	else if (m_state == State::MultiComment)
	{
		if (c == '/' && m_lastChar == '*')
		{
			setState(m_lastState);
		}
	}
	else if (m_lastChar == '/' && c == '*')
	{
		setState(State::MultiComment);
	}
	else if (m_lastChar == '/' && c == '/')
	{
		setState(State::Comment);
	}
	else if (m_state == State::Root)
	{
		if (c.isLetter())
		{
			setState(State::WidgetName);
			m_wName	+= c;
		}
		else if (c == '.')
		{
			setState(State::WidgetClass);
		}
		else if (c == '#')
		{
			setState(State::WidgetId);
		}
		else
		{
			return false;
		}
	}
	else if (m_state == State::WidgetName)
	{
		if (c == '{')
		{
			setState(State::Body);
		}
		else if (c.isLetter())
		{
			m_wName	+= c;
		}
		else if (c == '.')
		{
			setState(State::WidgetClass);
		}
		else if (c == '#')
		{
			setState(State::WidgetId);
		}
		else
		{
			return false;
		}
	}
	else if (m_state == State::WidgetClass)
	{
		if (c == '{')
		{
			setState(State::Body);
		}
		else if (c.isLetter() || c.isDigit())
		{
			m_wClass	+= c;
		}
		else if (c == '#')
		{
			setState(State::WidgetId);
		}
		else
		{
			return false;
		}
	}
	else if (m_state == State::WidgetId)
	{
		if (c == '{')
		{
			setState(State::Body);
		}
		else if (c.isLetter() || c.isDigit())
		{
			m_wId	+= c;
		}
		else if (c == '.')
		{
			setState(State::WidgetClass);
		}
		else
		{
			return false;
		}
	}
	else if (m_state == State::Body)
	{
		if (c.isLetter())
		{
			setState(State::OptionName);
			m_option		+= c;
		}
		else if (c == '}')
		{
			setState(State::Root);
		}
		else
		{
			return false;
		}
	}
	else if (m_state == State::OptionName)
	{
		if (c.isLetter() || c == '-')
		{
			m_option	+= c;
		}
		else if (c == ':')
		{
			setState(State::OptionValue);
		}
		else
		{
			return false;
		}
	}
	else if (m_state == State::OptionValue)
	{
		if (c == ';')
		{
			setState(State::Body);
			if (m_option == "font-size")
			{
				int size	= parseSize(m_optionValue);
			}
			else if (m_option == "font-family")
			{
				String fontFamily	= m_optionValue;
			}
			else if (m_option == "font-color")
			{
				Color c	= parseColor(m_optionValue);
			}
			else if (m_option == "font-wrap")
			{
				Font::Wrap wrap	= Font::Wrap::Word;
				if (m_optionValue == "None")
				{
					wrap	= Font::Wrap::None;
				}
				else if (m_optionValue == "Char")
				{
					wrap	= Font::Wrap::Char;
				}
			}
			else if (m_option == "font-v-align")
			{
				Font::VAlign vAlign		= Font::VAlign::Top;
				if (m_optionValue == "Middle")
				{
					vAlign	= Font::VAlign::Middle;
				}
				else if (m_optionValue == "Bottom")
				{
					vAlign	= Font::VAlign::Bottom;
				}
			}
			else if (m_option == "font-h-align")
			{
				Font::HAlign hAlign		= Font::HAlign::Left;
				if (m_optionValue == "Center")
				{
					hAlign	= Font::HAlign::Center;
				}
				else if (m_optionValue == "Right")
				{
					hAlign	= Font::HAlign::Right;
				}
			}
			else if (m_option == "border-color")
			{
				Color c	= parseColor(m_optionValue);
			}
			else if (m_option == "background-color")
			{
				Color c	= parseColor(m_optionValue);
			}
			else if (m_option == "background-gradient")
			{
				Gradient g	= parseGradient(m_optionValue);
			}
			else if (m_option == "border-radius")
			{
				if (m_optionValue.occurs(',') == 3)
				{
					String s	= "";
					int tl	= 0;
					int tr	= 0;
					int br	= 0;
					int bl	= 0;
					int borders	= 0;
					for (int i = 0; i < m_optionValue.length(); i++)
					{
						if (m_optionValue.charAt(i) != ',')
						{
							s	+= m_optionValue.charAt(i);
						}
						else
						{
							switch (borders)
							{
							case 0:
								tl	= parseSize(s);
								break;
							case 1:
								tr	= parseSize(s);
								break;
							case 2:
								br	= parseSize(s);
								break;
							}
							borders++;
							s	= "";
						}
					}
					if (borders == 3)
					{
						bl	= parseSize(s);
						s	= "";
					}
				}
				else if (!m_optionValue.contains(','))
				{
					int width	= parseSize(m_optionValue);
				}
				else
				{
					return false;
				}
			}
			else if (m_option == "border-width")
			{
				int width	= parseSize(m_optionValue);
			}
			m_optionValue	= "";
			m_option	= "";
			if (!m_parseSuccess)
			{
				return false;
			}
		}
		else
		{
			m_optionValue	+= c;
		}
	}
	else
	{
		return false;
	}
	return true;
}

void StyleParser::setState(State s)
{
	m_lastState		= m_state;
	m_state			= s;
}


Gradient StyleParser::parseGradient(String s)
{
	Gradient g;
	m_parseSuccess	= false;
	return g;
}

Color StyleParser::parseColor(String s)
{
	String num	= "";
	short r	= 0;
	short g	= 0;
	short b	= 0;
	short a	= 0;
	int commas	= 0;
	for (int i = 0; i < s.length(); i++)
	{
		Char act	= s.charAt(i);
		if (act.isDigit())
		{
			num	+= act;
		}
		else if (act == ',' || act == ']')
		{
			if (num.length() > 0)
			{
				switch (commas)
				{
				case 0:
					r	= num.toInt();
					break;
				case 1:
					g	= num.toInt();
					break;
				case 2:
					b	= num.toInt();
					break;
				case 3:
				default:
					a	= num.toInt();
					break;
				}
				commas++;
			}
		}
		else
		{
			m_parseSuccess	= false;
			return Color();
		}
	}
	m_parseSuccess	= true;
	return Color(r, g, b, a);
}

int StyleParser::parseSize(String s)
{
	m_parseSuccess	= true;
	return s.toInt();
}


O_END_NAMESPACE
